import { Entity, Column, Index, OneToMany } from 'typeorm';
import { BaseEntity } from '../common/base/base.entity';
import { DownloadRecord } from './download-record.entity';
import { Order } from './order.entity';

export const UserStatus = {
  ACTIVE: 'active',
  INACTIVE: 'inactive',
  BANNED: 'banned',
} as const;

/**
 * 用户实体
 * 对应数据库中的 users 表
 *
 * @Entity 装饰器：
 * - 参数 'users' 是数据库表名
 * - 如果不传参数，表名默认是类名的复数小写形式（user -> users）
 */
@Entity('users')
@Index('idx_email', ['email']) // 创建索引，提高查询速度
@Index('idx_username', ['username'])
export class User extends BaseEntity {
  // ==================== 基本信息 ====================

  /**
   * 用户名
   *
   * @Column 装饰器配置：
   * - type: 字段类型（varchar、int、text等）
   * - length: 字段长度
   * - unique: 是否唯一
   * - nullable: 是否可为空（默认 false）
   * - comment: 字段注释
   * - default: 默认值
   */
  @Column({
    type: 'varchar',
    length: 50,
    unique: true,
    comment: '用户名（唯一）',
  })
  username: string;

  /**
   * 邮箱
   * 用于登录
   */
  @Column({
    type: 'varchar',
    length: 100,
    unique: true,
    comment: '邮箱（唯一，用于登录）',
  })
  email: string;

  /**
   * 密码
   *
   * 注意：
   * 1. 存储的是加密后的密码（bcrypt）
   * 2. 长度设置为 255，因为加密后会变长
   * 3. select: false 表示查询时默认不返回密码字段
   */
  @Column({
    type: 'varchar',
    length: 255,
    select: false, // 默认查询不包含此字段，需要显式指定
    comment: '密码（bcrypt加密）',
  })
  password: string;

  /**
   * 手机号
   * 可选字段
   */
  @Column({
    type: 'varchar',
    length: 20,
    nullable: true, // 允许为空
    comment: '手机号',
  })
  phone?: string; // TypeScript 中用 ? 表示可选

  // ==================== 个人信息 ====================

  /**
   * 头像
   * 存储 URL 地址
   */
  @Column({
    type: 'varchar',
    length: 500,
    nullable: true,
    comment: '头像URL',
  })
  avatar?: string;

  /**
   * 昵称
   */
  @Column({
    type: 'varchar',
    length: 50,
    nullable: true,
    comment: '昵称',
  })
  nickname?: string;

  /**
   * 个人简介
   *
   * text 类型：
   * - 用于存储大段文本
   * - 不需要指定 length
   * - 最大 65535 字符
   */
  @Column({
    type: 'text',
    nullable: true,
    comment: '个人简介',
  })
  bio?: string;

  /**
   * 性别
   *
   * enum 类型：
   * - 限制字段只能是指定的值
   * - 在数据库层面保证数据完整性
   */
  @Column({
    type: 'enum',
    enum: ['male', 'female', 'other'],
    nullable: true,
    comment: '性别',
  })
  gender?: 'male' | 'female' | 'other'; // TypeScript 联合类型

  /**
   * 生日
   */
  @Column({
    type: 'date',
    nullable: true,
    comment: '生日',
  })
  birthday?: Date;

  // ==================== 角色与状态 ====================

  /**
   * 用户角色
   *
   * 为什么用 enum？
   * 1. 限制取值范围
   * 2. 便于权限判断
   * 3. 数据库层面保证数据正确
   */
  @Column({
    type: 'enum',
    enum: ['user', 'vip', 'svip', 'admin'],
    default: 'user',
    comment: '用户角色',
  })
  role: 'user' | 'vip' | 'svip' | 'admin';

  /**
   * 账号状态
   *
   * - active: 正常
   * - inactive: 未激活
   * - banned: 已封禁
   */
  @Column({
    type: 'enum',
    enum: ['active', 'inactive', 'banned'],
    default: 'active',
    comment: '账号状态',
  })
  status: 'active' | 'inactive' | 'banned';

  // ==================== 会员相关 ====================

  /**
   * 会员等级
   */
  @Column({
    type: 'enum',
    enum: ['free', 'vip', 'svip'],
    default: 'free',
    comment: '会员等级',
  })
  membershipLevel: 'free' | 'vip' | 'svip';

  /**
   * 会员到期时间
   */
  @Column({
    type: 'timestamp',
    nullable: true,
    comment: '会员到期时间',
  })
  membershipExpireAt?: Date;

  /**
   * 当月剩余下载配额
   *
   * int 类型：
   * - 存储整数
   * - default 设置默认值
   */
  @Column({
    type: 'int',
    default: 0,
    comment: '当月剩余下载配额',
  })
  downloadQuota: number;

  /**
   * 配额重置时间
   * 每月1号重置
   */
  @Column({
    type: 'timestamp',
    nullable: true,
    comment: '配额重置时间（每月1号）',
  })
  quotaResetAt?: Date;

  // ==================== 统计信息 ====================

  /**
   * 总下载次数
   */
  @Column({
    type: 'int',
    default: 0,
    comment: '总下载次数',
  })
  totalDownloads: number;

  /**
   * 总订单数
   */
  @Column({
    type: 'int',
    default: 0,
    comment: '总订单数',
  })
  totalOrders: number;

  /**
   * 总消费金额
   *
   * decimal 类型：
   * - 用于存储精确的小数（金额、价格等）
   * - (10,2) 表示总共10位，小数点后2位
   * - 例如：12345678.90
   *
   * 为什么不用 float？
   * - float 有精度问题，0.1 + 0.2 != 0.3
   * - 金额计算必须精确，必须用 decimal
   */
  @Column({
    type: 'decimal',
    precision: 10,
    scale: 2,
    default: 0,
    comment: '总消费金额',
  })
  totalSpent: number;

  // ==================== 安全相关 ====================

  /**
   * 邮箱是否已验证
   *
   * boolean 类型：
   * - 数据库中是 tinyint(1)
   * - TypeScript 中是 boolean
   */
  @Column({
    type: 'boolean',
    default: false,
    comment: '邮箱是否已验证',
  })
  emailVerified: boolean;

  /**
   * 手机号是否已验证
   */
  @Column({
    type: 'boolean',
    default: false,
    comment: '手机号是否已验证',
  })
  phoneVerified: boolean;

  /**
   * 最后登录时间
   */
  @Column({
    type: 'timestamp',
    nullable: true,
    comment: '最后登录时间',
  })
  lastLoginAt?: Date;

  /**
   * 最后登录IP
   */
  @Column({
    type: 'varchar',
    length: 50,
    nullable: true,
    comment: '最后登录IP',
  })
  lastLoginIp?: string;

  // ==================== 关联关系 ====================
  // 后面会详细讲解关联关系

  /**
   * 用户的订单
   * 一对多关系：一个用户可以有多个订单
   *
   * @OneToMany 装饰器：
   * - 第一个参数：关联的实体类型
   * - 第二个参数：反向关联的字段
   */
  @OneToMany(() => Order, (order) => order.user)
  orders: Order[];

  /**
   * 用户的下载记录
   */
  @OneToMany(() => DownloadRecord, (record) => record.user)
  downloadRecords: DownloadRecord[];
}
